package server.net;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Danon
 */
public class ServerCore implements Runnable {
    private ServerCore() {
        port = DEFAULT_PORT;
        timeout = DEFAULT_TIMEOUT;
    }
    
    public static ServerCore getInstance() {
        if(instance == null) instance = new ServerCore();
        return instance;
    }
    
    public void start() throws IllegalThreadStateException {
        if(thread==null || !running) 
            thread = new Thread(this);
        thread.start();
    }
    
    public void stop() {
        if(isRunning()) {
            terminated = true;
        } else throw new IllegalThreadStateException("Thread is not running.");
    }
    
    @Override
    public void run() {
        running = true;
        Logger.getLogger(ServerCore.class.getName()).log(Level.INFO, "Starting Provisioning Server...");
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            serverSocket.setSoTimeout(timeout);
            Logger.getLogger(ServerCore.class.getName()).log(Level.INFO, 
                    "Waiting for incoming connection on port {0}", ""+serverSocket.getLocalPort());
            while(!terminated) {
                try {
                    Socket s = serverSocket.accept();
                    RequestQueue.getInstance().handleSocket(s);           
                } catch (Exception ex) {}
            }
        } catch (IOException ex) {
            Logger.getLogger(ServerCore.class.getName()).log(Level.SEVERE, "ServerCore.run(): {0}", ex.toString());
        }
        try {
            serverSocket.close();
        } catch (Exception ex) {}
        Logger.getLogger(ServerCore.class.getName()).log(Level.INFO, 
                "Provisioning Server has been terminated.");
        running = false;
    }
    
    public synchronized boolean isRunning() {
        return running;
    }
    
    private static ServerCore instance;
    private static Thread thread;
    
    private ServerSocket serverSocket;
    private boolean terminated;
    private boolean running;
    
    private int timeout;
    private int port;
    
    public static final int DEFAULT_PORT = 45111;
    public static final int DEFAULT_TIMEOUT = 5000;
}
